"""This module is for getting and operation information from Gitlab."""

from cki_lib.logger import get_logger
import gitlab

LOGGER = get_logger(__name__)


class GetMRsInfo:
    """Class operates with Gitlab API using python gitlab library."""

    def __init__(self, project) -> None:
        """Initialize project."""
        self.project = project

    def get_number_of_merge_requests(self) -> int:
        """
        Get total number of MRs.

        :return: total number of MRs
        """
        merge_requests = self.project.mergerequests.list(iterator=True)
        LOGGER.info('Total merge requests: %d', merge_requests.total)

        return merge_requests.total

    def get_merge_requests_by_period(self, created_after: str, created_before: str):
        """
        Get all merge requests by time period.

        :param created_after: Created MRs after some time in the format 2022-10-29T08:00:00Z
        :param created_before: Created MRs before some time in the format 2022-10-29T08:00:00Z
        :return: A dictionary with integer values:
            - 'first_mr_id': an integer representing the first MR ID
            - 'last_mr_id': an integer representing the last MR ID
            - 'total_mrs': an integer representing the total number of MRs
        """
        merge_requests = self.project.mergerequests.list(get_all=True,
                                                         state='merged',
                                                         order_by='updated_at',
                                                         created_after=created_after,
                                                         created_before=created_before)
        if merge_requests:
            merge_requests_by_period = {'first_mr_id': merge_requests[-1].iid,
                                        'last_mr_id': merge_requests[0].iid,
                                        'total_mrs': len(merge_requests)}
        else:
            merge_requests_by_period = {'first_mr_id': 0,
                                        'last_mr_id': 0,
                                        'total_mrs': 0}
        return merge_requests_by_period

    def get_merge_request_state(self, mr_id: int) -> str:
        """
        Get state of an MR. There are 'opened', 'merged', 'closed' MRs.

        :param mr_id: ID of MR
        :return: state of MR
        """
        try:
            return self.project.mergerequests.get(mr_id).state
        except gitlab.exceptions.GitlabGetError:
            LOGGER.warning("Couldn't find an MR %d", mr_id)
        return None

    def check_merge_request_state(self, mr_id: int, state: str) -> bool:
        """
        Check if MR corresponds to the desired state.

        :param mr_id: ID of MR
        :param state: There are 'opened', 'merged', 'closed' MRs
        :return: True or False
        """
        return self.get_merge_request_state(mr_id) == state

    def _get_merge_request_pipelines_list(self, mr_id: int) -> list:
        """
        Get pipelines of the MR.

        :param mr_id: ID of MR
        :return: List of pipeline objects
        """
        return self.project.mergerequests.get(mr_id, lazy=True).pipelines.list(get_all=True)

    def get_list_bridges_of_pipeline(self, pipeline_id: int) -> list:
        """
        Get list of bridges (jobs) for the desired pipeline.

        :param pipeline_id: ID of the pipeline
        :return: list of bridges
        """
        return [b.attributes['downstream_pipeline']['id']
                for b in self.project.pipelines.get(pipeline_id,
                                                    lazy=True).bridges.list(iterator=True)]

    def _get_pipelines_attributes(self, mr_id: int) -> list:
        """
        Get all pipeline attributes, i.e. all the info about the pipeline.

        :param mr_id: ID of MR
        :return: pipeline attributes
        """
        return [pipeline.attributes for pipeline in self._get_merge_request_pipelines_list(mr_id)]

    def get_merge_request_pipelines_before_the_last_succeed(
            self, mr_id: int, pipeline_status: str = 'success') -> list:
        """
        Get all MR's pipelines before the last pipeline with the given pipeline status.

        :param mr_id:
        :param pipeline_status:
        :return: MR's pipelines before the last pipeline that succeed
        """
        merge_request_pipelines_list = self._get_pipelines_attributes(mr_id)
        index = next((i for i, p in enumerate(merge_request_pipelines_list)
                      if p['status'] == pipeline_status), None)
        return merge_request_pipelines_list[index + 1:] if index is not None else []
